package rwt.server;

import java.io.IOException;
import java.sql.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;

import org.eclipse.jetty.websocket.*;
import org.slf4j.*;

import rwt.server.core.*;
import rwt.server.db.*;

/**
 * A Java servlet that manages WebSocket connections for web throttles.
 */
@SuppressWarnings("serial")
public class WebSocketServlet extends HttpServlet
{
	private static final Logger logger = LoggerFactory.getLogger(WebSocketServlet.class);
	
	public static final int BUFFER_SIZE = 1024;
	public static final int MAX_IDLE_TIME = 60_000;
	
	private WebSocketFactory webSocketFactory;
	
	/**
	 * Initialize the servlet by creating the WebSocketFactory.
	 */
	@Override
	public void init() throws ServletException
	{
		// Create and configure WS factory
		webSocketFactory = new WebSocketFactory(new WebSocketFactory.Acceptor()
		{
			@Override
			public boolean checkOrigin(HttpServletRequest request, String origin)
			{
				// Allow all origins
				return true;
			}
			
			@Override
			public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
			{
				// Return new RailWebSocket for "rail" protocol connections
				
				logger.info("Web socket connection request from " + request.getRemoteHost() + ":"
						+ request.getRemotePort() + " (User: " + request.getRemoteUser() + ")");
				
				if ("rail".equals(protocol))
				{
					String userName = request.getRemoteUser();
					if (userName == null || userName.isEmpty())
						return null;
					
					User user = null;
					try (Connection conn = Database.getConnection())
					{
						user = DbUtil.getUserByName(conn, userName);
					}
					catch (SQLException e)
					{
						logger.warn("", e);
						return null;
					}
					if (user == null)
						return null;
					
					return RailServer.getClientManager().createClient(user);
				}
				return null;
			}
		});
		
		webSocketFactory.setBufferSize(WebSocketServlet.BUFFER_SIZE);
		webSocketFactory.setMaxIdleTime(WebSocketServlet.MAX_IDLE_TIME);
	}
	
	/**
	 * Handle the handshake GET request.
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
	{
		logger.info("Web socket GET");
		
		// If the WebSocket factory accepts the connection, then return
		if (webSocketFactory.acceptWebSocket(request, response))
			return;
		// Otherwise send an HTTP error.
		response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Websocket only");
	}
}
